package com.yang.core.plugins.retry;

import com.yang.core.api.RestClientBuilder;
import com.yang.core.model.RetryPolicy;
import com.yang.core.config.RestClientProperties;
import com.yang.core.extension.ExtensionPoint;
import com.yang.core.extension.RestClientExtension;
import lombok.extern.slf4j.Slf4j;

/**
 * 重试扩展
 * 开箱即用的重试功能
 */
@Slf4j
@ExtensionPoint(
    name = "retry",
    description = "智能重试扩展，支持多种重试策略",
    category = ExtensionPoint.Category.RETRY,
    order = 15
)
public class RetryExtension implements RestClientExtension {

    private final RestClientProperties.Retry retryConfig;

    public RetryExtension() {
        this.retryConfig = null; // 使用默认配置
    }

    public RetryExtension(RestClientProperties.Retry retryConfig) {
        this.retryConfig = retryConfig;
    }

    @Override
    public void extend(RestClientBuilder builder) {
        if (retryConfig == null || !retryConfig.isEnabled()) {
            return;
        }

        RetryPolicy policy = createRetryPolicy(retryConfig);
        builder.retryPolicy(policy);

        // 添加重试拦截器用于更精细的控制
        builder.addInterceptor(new RetryInterceptor(retryConfig));

        log.info("启用重试扩展，最大次数: {}, 初始延迟: {}ms, 退避倍数: {}",
                retryConfig.getMaxAttempts(),
                retryConfig.getInitialDelay().toMillis(),
                retryConfig.getBackoffMultiplier());
    }

    private RetryPolicy createRetryPolicy(RestClientProperties.Retry config) {
        return RetryPolicy.builder()
                .maxAttempts(config.getMaxAttempts())
                .initialDelay(config.getInitialDelay())
                .backoffMultiplier(config.getBackoffMultiplier())
                .maxDelay(config.getMaxDelay())
                .retryCondition(parseRetryCondition(config.getRetryOn()))
                .build();
    }

    private RetryPolicy.RetryCondition parseRetryCondition(String retryOn) {
        if (retryOn == null || retryOn.isEmpty()) {
            return RetryPolicy.RetryCondition.defaultCondition();
        }

        String[] conditions = retryOn.split(",");
        Class<? extends Exception>[] exceptionTypes = new Class[conditions.length];

        for (int i = 0; i < conditions.length; i++) {
            String condition = conditions[i].trim().toUpperCase();
            switch (condition) {
                case "TIMEOUT":
                    exceptionTypes[i] = java.util.concurrent.TimeoutException.class;
                    break;
                case "CONNECTION_ERROR":
                    exceptionTypes[i] = java.net.ConnectException.class;
                    break;
                case "SERVER_ERROR":
                    exceptionTypes[i] = org.springframework.web.client.HttpServerErrorException.class;
                    break;
                default:
                    exceptionTypes[i] = Exception.class;
                    break;
            }
        }

        return RetryPolicy.RetryCondition.retryOn(exceptionTypes);
    }
}